#include <cstdio>
#include <cstdlib>
#include <ostream>
#include <string.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

class Student {

public:
	// 无参构造函数，并且对age，name进行默认赋值
	Student():age(0),name((char *)"Tom"){
		cout << "调用无参构造函数" << endl;
	}
	// 带有一个参数构造，并且调用带有2个参数的构造函数
	Student(int age):Student((char *)"Jack",0){
	
	}
	// 带有两个参数构造
	Student(char *name, int age){
		cout << "调用2个参构造函数" << endl;
		this->name = (char *)malloc(sizeof(char)*24);
		strcpy(this->name,name);
		this->setAge(age);
	}

	/*
	 * 析构函数：对象被回收的时候调用，析构函数只能有一个
	 * 主要工作是释放类内部动态申请的内存
	 * */
	~Student(){
		cout << "--调用析构函数" << endl;
		if(this->getName())
		{
			// 进行回收内存
			cout << "进行回收内存" << endl;
			free(this->getName());
		} else {
			// 动态开辟的内存已经被回收
			cout << "动态开辟的内存已经被回收" << endl;
		}

	}

	// 拷贝构造函数，对象中默认都会有一个拷贝构造函数，用于兑奖之间的赋值
	Student(const Student &stu){
		// 拷贝构造函数属于【浅拷贝】
		cout << "拷贝构造函数" << endl;
		this->setAge(stu.age);
		this->setName(stu.name);
	}

private:
	char *name;
	int age;

public:
	// this代表当前类的指针
	void setName(char *name){
		this->name = name;
	}
	void setAge(int age){
		this->age = age;
	}

	int getAge(){
		return this->age;
	}

	char* getName(){
		return this->name;
	}
};

Student getStudent(char *name, int age)
{
	// 栈中开辟的内存，当函数调用完毕后，会调用拷贝构造函数，和析构函数
	Student stu(name,age);
	cout << "stu的地址：" << &stu << endl;
	return stu;
}

void printStudent(Student stu) // 函数中的参数 stu是从传递的参数中进行拷贝构造函数
{
	cout << "name:" << stu.getName() << "age:" << stu.getAge() << endl;
}

int main()
{

#if 0
	// 1.默认调用无参构造函数
	Student stu1;
	cout << stu1.getName() << stu1.getAge() << endl;
	stu1.setAge(11);
	stu1.setName((char*)"Jack");
	cout << stu1.getName() << stu1.getAge() << endl;
	cout << "-----------------" << endl;

	// 2.调用一个参数的构造函数
	Student stu2(28);
	cout << stu2.getName() << stu2.getAge() << endl;
	cout << "-----------------" << endl;

	// 3.使用new关键字，new出来的是一个Student的指针类型
	Student *stu3 = new Student((char *)"Amil",25);
	cout << stu3->getName() << stu3->getAge() << endl;
	cout << "-----------------" << endl;
	// 释放new出来的对象，此时会调用类中的析构函数
	delete(stu3);
	
	// 4.malloc动态申请内存的方式创建Student，这种方式不会经过构造函数
	Student *stu4 = (Student *)malloc(sizeof(Student));
	stu4->setAge(31);
	stu4->setName((char *)"Oppe");
	cout << stu4->getName() << stu4->getAge() << endl;
	cout << "-----------------" << endl;
#endif

#if 0
	// 情形一："="会调用拷贝构造函数
	Student stu5((char *)"Name5",25);
	Student stu6 = stu5; 	// stu5调用对象的拷贝构造函数给stu6进行赋值
	cout << stu6.getName() << stu6.getAge() << endl;
	cout << "-----------------stu7" << endl;
	Student stu7;  			
	stu7 = stu6; 			// stu6并不会调用拷贝构造函数
	cout << stu7.getName() << stu7.getAge() << endl;	

	// 情形二：对象当做参数返回的时候，会调用拷贝构造函数，并且会调用析构函数
	Student stu8  = getStudent((char *)"JKH", 14);
	cout << "stu8的地址：" << &stu8 << endl;
	cout << stu8.getName() << stu8.getAge() << endl;

	// 情形三：对象当做参数传递的时候，进入函数的时候，会先进行拷贝构造函数，然后函数执行完毕还会对对象进行析构
	Student stu9((char *)"HHHP",45);
	printStudent(stu9);
	cout << stu9.getName() << stu9.getAge() << endl;
#endif

	// 情形四：多次调用析构函数报错,应对方式是：在拷贝构造函数中使用深拷贝
	Student stu10 = getStudent((char *)"aaa-", 120);
	printStudent(stu10);

	//getchar();
	
	// 程序结束后会调用对象的析构函数
	return 0;
}


